#include <avr/io.h>
#include <avr/interrupt.h>
#include <compat/ina90.h>

#include "CSpi.h"
#include "CFram.h"

/* NOTE FOR FRAM CHIP ***************************************
 Important: The /CS must go inactive after an
 operation is complete and before a new op-code
 can be issued. There is one valid op-code only per
 active chip select.
 ************************************************************/
// functions
CFram::CFram(CSpi *_spi) {
  spi = _spi;
  CS_DIS();
}

u08 CFram::readbyte(u32 memAddr) {
  u08 data;
  CS_EN();
  spi->transferbyte(SPIEEPROM_CMD_READ);
  spi->transferbyte(memAddr >> 8);
  spi->transferbyte(memAddr & 0x00FF);
  data = spi->transferbyte(0xFF);
  CS_DIS();
  return data;
}

void CFram::writebyte(u32 memAddr, u08 data) {
  wr_enable();
  CS_EN();
  // send command
  spi->transferbyte(SPIEEPROM_CMD_WRITE);
  // send address
  spi->transferbyte(memAddr >> 8);
  spi->transferbyte(memAddr & 0x00FF);
  // send data to be written
  spi->transferbyte(data);
  CS_DIS();
}

void CFram::wr_enable(void) {
  CS_EN();
  spi->transferbyte(SPIEEPROM_CMD_WREN);
  CS_DIS();
}

void CFram::wr_disable(void) {
  CS_EN();
  spi->transferbyte(SPIEEPROM_CMD_WRDI);
  CS_DIS();
}

u08 CFram::readstatus(void) {
  u08 status;
  CS_EN();
  spi->transferbyte(SPIEEPROM_CMD_RDSR);
  status = spi->transferbyte(0xFF);
  CS_DIS();
  return status;
}

void CFram::readblock(u32 memAddr, u08 *data, u32 len) {
  CS_EN();
  spi->transferbyte(SPIEEPROM_CMD_READ);
  spi->transferbyte(memAddr >> 8);
  spi->transferbyte(memAddr & 0x00FF);
  while (len) {
    len--;
    *data = spi->transferbyte(0xFF);
    data++;
  }
  CS_DIS();
}

void CFram::writeblock(u32 memAddr, u08 *data, u32 len) {
  wr_enable();
  CS_EN();
  spi->transferbyte(SPIEEPROM_CMD_WRITE);
  spi->transferbyte(memAddr >> 8);
  spi->transferbyte(memAddr & 0x00FF);
  while (len) {
    len--;
    spi->transferbyte(*data++);
  }
  CS_DIS();
}

